/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc. 
 *  
 * SPDX-License-Identifier: Apache-2.0.
 * 
 * @Date: 2021-08-23 16:23:05
 * @LastEditTime: 2021-08-26 18:01:08
 * @Description:  This files is for 
 * 
 * @Modify History: 
 *  Ver   Who        Date         Changes
 * ----- ------     --------    --------------------------------------
 */
#ifndef BSP_DRIVERS_ETH_F_GMAC_H
#define BSP_DRIVERS_ETH_F_GMAC_H

#ifdef __cplusplus
extern "C"
{
#endif

#include "parameters.h"
#include "ft_types.h"
#include "ft_error_code.h"
#include "ft_debug.h"

/* lower 32 bit + high 16 bit */
#define GMAC_MAC_ADDR_LEN      6
#define GMAC_MTU               1500

enum
{
    GMAC_TX_COMPLETE_EVT = 0,
    GMAC_RX_COMPLETE_EVT,
    GMAC_LINK_STATUS_EVT,
    GMAC_PHY_STATUS_EVT,
    GMAC_DMA_ERR_EVT,

    GMAC_INTR_EVT_NUM
};

enum
{
    GMAC_CTRL_INTR = 0,
    GMAC_DMA_INTR,

    GMAC_MAX_INTR_TYPE
};

enum
{
    GMAC_AUTONEGOTIATION_DISABLE = 0,
    GMAC_AUTONEGOTIATION_ENABLE
};

/* The forced speed, 10Mb, 100Mb, gigabit, 2.5Gb, 10GbE. */
enum
{
    GMAC_SPEED_10 = 10,
    GMAC_SPEED_100 = 100,
    GMAC_SPEED_1000 = 1000,
    GMAC_SPEED_2500 = 2500,
    GMAC_SPEED_10000 = 10000
};

enum
{
    GMAC_MODE_HALFDUPLEX = 0,
    GMAC_MODE_FULLDUPLEX = 1
};

enum
{
    GMAC_CHECKSUM_BY_SOFTWARE = 0,
    GMAC_CHECKSUM_BY_HARDWARE
};

enum
{
    GMAC_MEDIA_INTERFACE_RGMII = 0,
    GMAC_MEDIA_INTERFACE_MII
};

typedef struct
{
    volatile u32 status;
    u32 ctrl;
    u32 buf1Addr;
    u32 next;
} GmacDmaDesc;

typedef struct
{
    u32 instanceId; /* Id of device */
    u32 baseAddr;   /* base address of register */
    u32 irqNum;     /* irq num */
    u32 irqPrority; /* irq priority */     
    char irqName[16]; /* irq name */
    boolean enableIrq; /* enabel irq or not */
    s32 phyAddr;    /* Phy Ic Addre1 */
    u32 clkMDC;     /* MDC clock access PHY. [1.0MHz ~2.5MHz] */
    u32 autoNegot;  /* AutoNegotiation or not */
    u32 speed;      /* Sets the Ethernet speed: 10/100/1000 Mbps. */
    u32 duplexMode; /* Selects the MAC duplex mode: Half-Duplex or Full-Duplex mode */
    u32 checkSumMode; /* hardware or software checksum */
    u32 mediaInterface; /* media-independent interface */
    u8 macAddr[GMAC_MAC_ADDR_LEN]; /* 6 bytes Mac address */
} GmacConfig;

typedef struct
{
    u32 descIdx;  /* For Current Desc position */
    u32 descBufIdx; /* For Current Desc buffer buf position */
    u32 descMaxNum; /* Max Number for  Desc and Desc buffer */
    u8 *descBufBase; /*  Desc buffer Base */
} GmacRingDescData;

typedef void (*GmacEvtHandler)(void *pCtrl);

typedef struct 
{
    GmacConfig config;
    u32 isReady;

    volatile GmacDmaDesc *rxDesc;
    GmacRingDescData rxRing;

    volatile GmacDmaDesc *txDesc;
    GmacRingDescData txRing;

    GmacEvtHandler evtHandler[GMAC_INTR_EVT_NUM];
} GmacCtrl;

const GmacConfig *GmacLookupConfig(u32 instanceId);
u32 GmacCfgInitialize(GmacCtrl *pCtrl, const GmacConfig *pConfig);
u32 GmacHwInitialize(GmacCtrl *pCtrl);
u32 GmacDmaInitRxDescRing(GmacCtrl *pCtrl, GmacDmaDesc *pRxDescTbl, u8 *pRxBuf, u32 descPreBufLen, u32 rxBufCnt);
u32 GmacDmaInitTxDescRing(GmacCtrl *pCtrl, GmacDmaDesc *pTxDescTbl, u8 *pTxBuf, u32 descPreBufLen, u32 txBufCnt);
u32 GmacDmaStart(GmacCtrl *pCtrl);
u32 GmacIntrInit(GmacCtrl *pCtrl);
u32 GmacGetIntrMask(GmacCtrl *pCtrl, u32 intrType);
void GmacSetIntrMask(GmacCtrl *pCtrl, u32 intrType, u32 mask, boolean enable);
void GmacRegisterEvtHandler(GmacCtrl *pCtrl, u32 evt, GmacEvtHandler handler);
void GmacProbe(const GmacCtrl *pCtrl);

#define GMAC_SUCCESS              FT_SUCCESS  
#define GMAC_ERR_TIMEOUT          FT_MAKE_ERRCODE(ErrModBsp, ErrBspEth, BIT(0))
#define GMAC_ERR_INVALID_DMA_MEM  FT_MAKE_ERRCODE(ErrModBsp, ErrBspEth, BIT(1))
#define GMAC_ERR_NOT_READY        FT_MAKE_ERRCODE(ErrModBsp, ErrBspEth, BIT(2))
#define GMAC_ERR_TRANS_FAILED     FT_MAKE_ERRCODE(ErrModBsp, ErrBspEth, BIT(3))
#define GMAC_ERR_PHY_NOT_SUPPORT  FT_MAKE_ERRCODE(ErrModBsp, ErrBspEth, BIT(4))

#define GMAC_DEBUG_TAG "GMAC"
#define GMAC_ERROR(format, ...)   FT_DEBUG_PRINT_E(GMAC_DEBUG_TAG, format, ##__VA_ARGS__)
#define GMAC_INFO(format, ...)    FT_DEBUG_PRINT_I(GMAC_DEBUG_TAG, format, ##__VA_ARGS__)
#define GMAC_DEBUG(format, ...)   FT_DEBUG_PRINT_D(GMAC_DEBUG_TAG, format, ##__VA_ARGS__)
#define GMAC_WARN(format, ...)    FT_DEBUG_PRINT_W(GMAC_DEBUG_TAG, format, ##__VA_ARGS__)

#define GMAC_RETRY_TIMES          500

#ifdef __cplusplus
}
#endif

#endif // !